import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { User } from 'src/database/entitys/user.entity';
import { In, Repository } from 'typeorm';
import { QueryUserDto } from './dto/query-user.dto';
import { UserRole } from 'src/database/entitys/user-role.entity';
import { Role } from 'src/database/entitys/role.entity';
import { UpdateUserDto } from './dto/update-user.dto';

/**
 * 用户服务
 */
@Injectable()
export class UserService {
  constructor(
    @InjectRepository(User)
    private userRepository: Repository<User>,
    @InjectRepository(UserRole)
    private userRoleRepository: Repository<UserRole>,
    @InjectRepository(Role)
    private roleRepository: Repository<Role>
  ) {}

  /**
   * 查询所有用户 分页 带查询条件 返回总数
   */
  async findAll({ page, size, username, name }: QueryUserDto): Promise<{ users: User[]; total: number }> {
    const queryBuilder = this.userRepository
      .createQueryBuilder('user')
      .skip((page - 1) * size)
      .take(size)
      .leftJoinAndSelect('user.userRoles', 'userRoles')
      .leftJoinAndSelect('userRoles.role', 'role')
      .orderBy('user.userId', 'DESC');

    if (username.trim()) {
      queryBuilder.where('user.username LIKE :username', { username: `%${username.trim()}%` });
    }

    if (name?.trim()) {
      queryBuilder.andWhere('user.name LIKE :name', { name: `%${name.trim()}%` });
    }

    const [users, total] = await queryBuilder.getManyAndCount();

    return {
      users,
      total,
    };
  }

  /**
   * 根据用户名查询用户
   * @param username 用户名
   */
  async findOne(username: string): Promise<User> {
    return await this.userRepository.findOneBy({ username });
  }

  /**
   * 根据邮箱查询用户信息
   */
  async findByEmail(email: string): Promise<User> {
    return await this.userRepository.findOneBy({ email });
  }

  /**
   * 删除用户
   * @param user 用户
   */
  async remove(user: User) {
    await this.removeUserRole(user.userId);
    return await this.userRepository.delete(user.userId);
  }

  /**
   * 新增
   */
  async save(updateUser: UpdateUserDto): Promise<User> {
    const user = await this.userRepository.save(updateUser);
    if (updateUser.roleIds) {
      await this.updateUserRole(user, updateUser.roleIds);
    }
    return user;
  }

  /** 更新用户角色关系 */
  async updateUserRole(user: User, roleIds: Number[]) {
    // 2. 删除用户角色关系
    await this.userRoleRepository.delete({ user: { userId: user.userId } });

    // 3. 根据新的角色ID查找菜单
    const roles = await this.roleRepository.findBy({ roleId: In(roleIds) });

    // 4. 创建新的菜单角色关联
    const userRoles = roles.map((role) => {
      const userRole = new UserRole();
      userRole.user = user;
      userRole.role = role;
      return userRole;
    });

    // 5. 保存新的用户角色关联
    return await this.userRoleRepository.save(userRoles);
  }

  /** 删除用户角色关联关系 */
  async removeUserRole(userId: number) {
    return await this.userRoleRepository.delete({ user: { userId } });
  }
}
